package com.clw.service.impl;

import com.clw.dataobject.DataDictionary;
import com.clw.dataobject.DataDictionaryDetail;
import com.clw.dto.DictionaryDTO;
import com.clw.enums.ResultEnum;
import com.clw.exception.SellException;
import com.clw.repository.DataDictionaryDetailRepository;
import com.clw.repository.DataDictionaryRepository;
import com.clw.service.DataDictionaryService;
import com.clw.utils.DateUtils;
import com.clw.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by MYQ on 2017/10/28.
 */
@Service
public class DataDictionaryServiceImpl implements DataDictionaryService {
    @Autowired
    private DataDictionaryRepository repository;

    @Autowired
    private DataDictionaryDetailRepository detailRepository;
    
    private Specification<DataDictionary> getSpecification(String name, String code, String startTime, String endTime){
        return new Specification<DataDictionary>() {
            @Override
            public Predicate toPredicate(Root<DataDictionary> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (StringUtils.isNotEmpty(name)) {
                    predicates.add(criteriaBuilder.like(root.get("name"), "%" + name + "%"));
                }
                if (StringUtils.isNotEmpty(code)) {
                    predicates.add(criteriaBuilder.like(root.get("code"), "%" + code + "%"));
                }
                if (StringUtils.isNotEmpty(startTime)){
                    Date start= DateUtils.stringToDate(startTime);
                    predicates.add(criteriaBuilder.greaterThan(root.get("createTime"),start));
                }
                if (StringUtils.isNotEmpty(endTime)){
                    Date end=DateUtils.addDay(endTime,1);
                    predicates.add(criteriaBuilder.lessThan(root.get("createTime"),end));
                }
                return criteriaQuery.where(predicates.toArray(
                        new Predicate[predicates.size()])).getRestriction();
            }
        };
    }

    @Override
    public DataDictionary findOne(Integer id) {
        return repository.findOne(id);
    }

    @Override
    public List<DataDictionary> findAll(String name,String code, String startTime, String endTime) {
        return repository.findAll(getSpecification(name,code,startTime,endTime));

    }

    @Override
    public Page<DataDictionary> findAll(String name, String code, String startTime, String endTime, Pageable pageable) {
        return repository.findAll(getSpecification(name,code,startTime,endTime),pageable);
    }

    @Override
    public DictionaryDTO save(DictionaryDTO dictionaryDTO) {
        DataDictionary dataDictionary=new DataDictionary();
        BeanUtils.copyProperties(dictionaryDTO,dataDictionary);
        DataDictionary result=repository.save(dataDictionary);
        for (DataDictionaryDetail detail:dictionaryDTO.getList()) {
            detail.setMainId(result.getId());
            detail.setStatus(1);
            detailRepository.save(detail);
        }

        return dictionaryDTO;
    }

    @Override
    @Transactional
    public void del(DataDictionary dataDictionary) {
        Integer mainId=dataDictionary.getId();
        repository.delete(dataDictionary);
        detailRepository.deleteAllByMainId(mainId);
    }

    @Override
    public Long getSize(String name,String code, String startTime, String endTime) {
        return repository.count(getSpecification(name,code,startTime,endTime));
    }

    @Override
    public List<DataDictionary> findAll() {
        return repository.findAll();
    }

    @Override
    public List<DataDictionaryDetail> findDetail(Integer id) {
        return detailRepository.findAllByMainId(id);
    }

    @Override
    public DictionaryDTO update(DictionaryDTO dictionaryDTO) {
        List<DataDictionaryDetail> oldValueList=detailRepository.findAllByMainId(dictionaryDTO.getId());
        List<DataDictionaryDetail> newValueList=dictionaryDTO.getList();
        if (newValueList!=null&&newValueList.size()>0){
            for (DataDictionaryDetail oldValue:oldValueList){
                boolean isUpdate=false;
                for (DataDictionaryDetail newValue:newValueList){
                    if (oldValue.getId().equals(newValue.getId())){
                        newValue.setMainId(oldValue.getMainId());
                        detailRepository.save(newValue);
                        isUpdate=true;
                        break;
                    }
                }
                if (!isUpdate){
                    detailRepository.delete(oldValue);
                }
            }

            for (DataDictionaryDetail value:newValueList){
                if (StringUtils.isEmpty(value.getId())){
                    value.setMainId(dictionaryDTO.getId());
                    detailRepository.save(value);
                }
            }

        }
        DataDictionary dataDictionary=new DataDictionary();
        BeanUtils.copyProperties(dictionaryDTO,dataDictionary);
        repository.save(dataDictionary);
        return dictionaryDTO;
    }

    @Override
    public List<DataDictionaryDetail> getDetailByCode(String code) {
        DataDictionary dictionary=repository.findByCode(code);
        if (dictionary==null){
            throw new SellException(ResultEnum.NO_FOUND);
        }
        return detailRepository.findAllByMainId(dictionary.getId());
    }
}
